home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * TE_FileIO.c *
- * *
- * XTND import and export routines for TESample. *
- * *
- * Copyright © 1988 Claris Corporation *
- * All Rights Reserved *
- * *
- ************************************************************************/
-
-
- #ifdef THINK_C
- #define const /* when is ThinkC going to get with the program? */
- #else
- #pragma load "MacIncludes"
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #include "TESample.h"
- #include ":::XTND Headers:XTNDCIncludes:XTNDInterface.h"
- #include ":::XTND Headers:XTNDCIncludes:XTNDTextTranslator.h"
-
- /*------------------------- Useful Constants ---------------------------*/
-
- #define QUICKDRAWSTYLES (bold+italic+underline+outline+shadow)
- #define STRINGS 25002
- #define NUMSTDS 3
- #define FALSE 0
- #define TRUE 1
- #define STD_FILETYPE(iType) (((iType) == 0) ? 'MOOD': ((iType) == 1) ? 'MOOS' : 'TEXT')
-
-
- /*-------------------------Function prototypes--------------------------*/
-
- /*----------External Functions----------*/
- extern short gNumDocuments;
- extern void DoNew(void);
- extern void AlertUser( short, short );
- extern void DoZoomWindow(WindowPtr, short);
- extern void AdjustScrollValues( WindowPtr window, Boolean canRedraw );
-
- /*----------Externally visible functions in this file----------*/
- void XTNDInit(void);
- void DoOpen(void);
- void DoSave(Boolean);
-
- /*----------Static functions in this file----------*/
- static void ReadFile(TransDescribe *, SFReply);
- static OSErr ReadPlainTextFile(const SFReply *pTheReply, TEHandle hTE);
- static void SaveFile(TransDescribe *, SFReply);
- static OSErr SavePlainTextFile(Str255 fileName, short vRefNum, long dirID,
- TEHandle hTE, Boolean saveAll);
- static OSErr SaveNewPlainTextFile(const SFReply *pTheReply, OSType fileType,
- TEHandle hTE, Boolean saveAll, short *pVRefNum, long *pDirID);
- static void Getnextstory(ImportParmBlkPtr);
- static void RGBFromXTND(RGBColor *, short);
- static short RGBToXTND(RGBColor);
- static void ZeroBlock(register void *, register long);
-
- /*-------------------------Global Variables-----------------------------*/
-
- static short Load_stored = 1; /* Selected translator in GetFile popup menu (initially "All Available") */
- static short Save_stored = 1; /* Selected translator in PutFile popup menu */
- static Boolean gXTNDLibOK = FALSE; /* Indicates whether XTND initialized successfully or not */
-
- extern CursHandle WATCH; /* Watch Cursor */
-
- TransProcPtr gImportTranslator; /* Pointer to code of Import Translator */
- TransProcPtr gExportTranslator; /* Pointer to code of Export Translator */
-
- TransDescribe Standards[NUMSTDS]; /* Array of types that this application can read */
-
-
- /*----------------------------------------------------------------------*/
- /* XTNDInit initializes the XTND Library and sets the global flag */
- /* gXTNDLibOK to TRUE if the library was successfully initialized. */
- /* Also sets up an array of translator descriptor records which */
- /* describe the files our application is able to read or write without */
- /* the need of external translators. This global array is used when */
- /* calling the XTND Library routines XTNDGetFile() and XTNDPutFile(). */
- /*----------------------------------------------------------------------*/
- void XTNDInit(void)
- {
- register long iStd;
- Str255 XTNDSystemName, ClarisFolderName;
-
- /* one-time initialization of the XTND Library… */
- GetIndString(XTNDSystemName, xtndNames, xtndSystem);
- GetIndString(ClarisFolderName, clarisNames, clarisFolder);
-
- gXTNDLibOK = (XTNDInitTranslators(kTransVersion, XTNDSystemName, ClarisFolderName) == noErr);
-
- /*
- The application should really check here for an error from InitTranslators
- - it may need to report something to the user
- */
-
- for (iStd = 0; iStd < NUMSTDS; iStd++)
- {
- Standards[iStd].version = 2;
- Standards[iStd].translatorType = 'FLTI';
- Standards[iStd].codeResID = 0;
- Standards[iStd].FDIFResID = -1;
- Standards[iStd].numVersBytes = 0;
- Standards[iStd].unused1 = 0;
- Standards[iStd].pathLength = 0;
- Standards[iStd].flags = 0;
- Standards[iStd].numMatches = 1;
- Standards[iStd].matches[0].docCreator = 'XTND';
- Standards[iStd].matches[0].docType = STD_FILETYPE(iStd);
- Standards[iStd].matches[0].exactMatch = FALSE;
- GetIndString(Standards[iStd].name, STRINGS, iStd + 1);
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- /* DoOpen is the handler for the open command. Prompts the user for */
- /* the file to open. If the user selects a file a new document window */
- /* is created and the file is read in. If the XTND Library was */
- /* successfully initialized its XTNDGetFile() routine is used to get */
- /* the user’s document selection, otherwise the Standard File */
- /* SFGetFile() routine is used. */
- /*----------------------------------------------------------------------*/
- void DoOpen(void)
- {
- Boolean getIt;
- SFReply myReply;
- SFParamBlock myXSFPB;
-
- if (gXTNDLibOK) {
- ZeroBlock(&myXSFPB,sizeof(SFParamBlock));
- myXSFPB.allowFlags = allowText;
- myXSFPB.numStandard = NUMSTDS;
- myXSFPB.standard = Standards;
- myXSFPB.ioResult = 0;
- myXSFPB.fileReply = &myReply;
- myXSFPB.XTNDDlogHook = nil; /* (XTNDDlgHookProcPtr) MyDlg; */
- myXSFPB.currentMenuItem = Load_stored;
- myXSFPB.where.v = myXSFPB.where.h = 0;
- myXSFPB.prompt = (unsigned char *)"\pSelect a file to open";
- myXSFPB.buttonTitle = (unsigned char *)"\pOpen";
- myXSFPB.dialogID = 0;
- myXSFPB.SFFilterProc = nil;
- myXSFPB.showAllFiles = FALSE;
- myXSFPB.useTransList = FALSE;
- myXSFPB.myFileFilter = nil;
- myReply.good = TRUE;
- getIt = XTNDGetFile(&myXSFPB);
- Load_stored = myXSFPB.currentMenuItem;
- } else {
- Point where = {0x40, 0x40};
- SFTypeList myTypes = {'TEXT'};
-
- SFGetFile(where, NULL, NULL, 1, myTypes, NULL, &myReply);
- getIt = myReply.good;
- }
- if (getIt) {
- short numDocuments = gNumDocuments;
-
- DoNew();
- if (numDocuments != gNumDocuments) { /* Did we open a new window ? */
- if (gXTNDLibOK && myXSFPB.chosenTranslator > myXSFPB.numStandard)
- ReadFile(myXSFPB.theChosenTranslator, myReply); /* Read the file in using XTND. */
- else {
- /* Use the appropriate internally supported method of reading the file.
- While our application claims to support three (NUMSTDS) formats, they are
- all actually simple TEXT documents. */
- (void)ReadPlainTextFile(&myReply, ((DocumentPeek)FrontWindow())->docTE);
- }
- }
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- /* DoSave is the handler for the Save and SaveAs commands. The */
- /* parameter saveAs specifies the Save As command when it is TRUE. */
- /* When handling a SaveAs command the user is prompted for a filename */
- /* and location to save the document. The window title of the */
- /* frontmost window is used as a default filename. If the user */
- /* specifies a filename and location the file is created (deleting */
- /* any previously existing one) and the contents of the frontmost */
- /* document window are written to it. If the XTND Library was */
- /* successfully initialized its XTNDPutFile() routine is used to get */
- /* the user’s document selection, otherwise the Standard File */
- /* SFGetFile() routine is used. Handling of the Save command is */
- /* currently not implemented. If DoSave() is called with saveAs FALSE */
- /* it will simply beep. */
- /*----------------------------------------------------------------------*/
- void DoSave(Boolean saveAs)
- {
- Str255 wTitle;
- Boolean putIt;
- SFReply myReply;
- SFParamBlock myXSFPB;
- register WindowPtr window = FrontWindow();
-
- GetWTitle(window, wTitle);
- if (!saveAs) {
- /* Handle a simple Save routine here. */
- SysBeep(1);
- return;
- }
- if (gXTNDLibOK) {
- ZeroBlock(&myXSFPB,sizeof(SFParamBlock));
- myXSFPB.allowFlags = allowText + allowExport;
- myXSFPB.numStandard = NUMSTDS;
- myXSFPB.standard = Standards;
- myXSFPB.ioResult = 0;
- myXSFPB.fileReply = &myReply;
- myXSFPB.applicNativeType = 'TEXT';
- myXSFPB.XTNDDlogHook = nil; /* (XTNDDlgHookProcPtr) MyDlg; */
- myXSFPB.currentSaveItem = Save_stored;
- myXSFPB.where.v = myXSFPB.where.h = 0;
- myXSFPB.prompt = (unsigned char *)"\pExport File";
- myXSFPB.buttonTitle = (unsigned char *)"\pSave";
- myXSFPB.origName = wTitle;
- myXSFPB.dialogID = 0;
- myXSFPB.SFFilterProc = nil;
- myXSFPB.useTransList = FALSE;
- myXSFPB.myFileFilter = nil;
- myReply.good = TRUE;
- putIt = XTNDPutFile(&myXSFPB);
- Save_stored = myXSFPB.currentSaveItem;
- } else {
- Point where = {0x40, 0x40};
- Str255 myPrompt = "\pSave document as:";
-
- SFPutFile(where, myPrompt, wTitle, NULL, &myReply);
- putIt = myReply.good;
- }
- if (putIt) {
- if (gXTNDLibOK && myXSFPB.chosenTranslator > myXSFPB.numStandard)
- SaveFile(myXSFPB.theChosenTranslator, myReply); /* Save the file using XTND. */
- else {
- long dirID;
- short vRefNum;
-
- /* Use the appropriate internally supported method of saving the file.
- While our application claims to support three (NUMSTDS) formats, they are
- all actually simple TEXT documents. The only differentiation we make is
- the fileType we create the documents as. */
- (void)SaveNewPlainTextFile(&myReply, STD_FILETYPE(myXSFPB.chosenTranslator),
- ((DocumentPeek)FrontWindow())->docTE, /*saveAll*/ TRUE, &vRefNum, &dirID);
- }
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- /* ReadFile reads the file in using XTND. It loads the translator, */
- /* initializes the import parameter block, and sends commands to the */
- /* translator to read in the document. When it is finished, it */
- /* releases the translator. */
- /*----------------------------------------------------------------------*/
- static void ReadFile(pChosenOne, theReply)
- register TransDescribe *pChosenOne;
- SFReply theReply;
- {
- register WindowPtr window = FrontWindow();
- register Ptr dummyptr;
- register long TESlop = sizeof(TextStyle)+500L;
-
- PictMisc **pm;
- ImportParmBlock importPB;
- ParamBlockRec hfsPB;
- TEHandle te;
- Fixed Parafmt[9];
- TabSpec Tabs[20];
- Point MinusOne;
- Rect tempRect;
- Str255 Buffer;
- unsigned char Marker[10];
- short fnum = 0, resfnum = 0, tempErr, fserr, *aPtr;
- long count, textrun = 0L;
- TextStyle newStyle;
- Str255 theNumber;
- unsigned long now;
-
- SetCursor(*WATCH);
-
- SetWTitle(window, theReply.fName);
-
- if (fserr = XTNDLoadTranslator(pChosenOne, &gImportTranslator)) {
- AlertUser(eTranslatorLoad,fserr);
- return;
- }
-
- MinusOne.h = MinusOne.v = -1;
- te = ((DocumentPeek) window)->docTE;
- importPB.textBuffer = (Ptr)Buffer;
- importPB.result = noErr;
- importPB.textLength = 0;
- importPB.txtFace = 0; /* Plain */
- importPB.txtSize = 0;
- importPB.txtFont = helvetica;
- importPB.txtColor = 0;
- importPB.txtJust = 0; /* Left */
- importPB.paraFmts = Parafmt;
- importPB.tabs = Tabs;
- importPB.numCols = 1;
- importPB.currentStory = mainStory;
- importPB.miscData = 0;
- importPB.storyHeight = 0;
- importPB.decimalChar = '.';
- importPB.autoHyphenate = TRUE;
- importPB.printRecord = NULL;
- importPB.startPageNum = 1;
- importPB.startFootnoteNum = 1;
- importPB.footnoteText = Marker;
- importPB.footnoteText[0] = 0;
- importPB.rulerShowing = 2;
- importPB.doubleSided = FALSE;
- importPB.titlePage = FALSE;
- importPB.endnotes = FALSE;
- importPB.showInvisibles = FALSE;
- importPB.showPageGuides = TRUE;
- importPB.showPictures = TRUE;
- importPB.autoFootnotes = TRUE;
- importPB.pagePoint = MinusOne;
- importPB.datePoint = MinusOne;
- importPB.timePoint = MinusOne;
- importPB.smartQuotes = TRUE;
- importPB.fractCharWidths = FALSE;
- importPB.hRes = 72;
- importPB.vRes = 72;
- importPB.theReply = theReply;
- importPB.thisTranslator = *pChosenOne;
-
- if (OpenRFPerm(theReply.fName, theReply.vRefNum, fsRdPerm) == -1)
- {
- if ((tempErr = ResError()) != eofErr) { /* No resource fork found */
- AlertUser(eResFailed,tempErr);
- (void)XTNDReleaseTranslator(pChosenOne);
- return;
- }
- UseResFile(pChosenOne->resRefNum); /* For translators expecting to be the current resource file */
- } else { /* If there is a resource fork for this file, read the resources */
- resfnum = CurResFile();
- importPB.refNum = resfnum;
- importPB.directive = importGetResources;
- (*gImportTranslator)(&importPB);
- if (importPB.result)
- {
- AlertUser(eResReadFail,importPB.result);
- CloseResFile(resfnum);
- (void)XTNDReleaseTranslator(pChosenOne);
- return;
- }
- }
-
- /* Open the file read only */
-
- fserr = 0;
- hfsPB.ioParam.ioNamePtr = theReply.fName;
- hfsPB.ioParam.ioVRefNum = theReply.vRefNum;
- hfsPB.ioParam.ioVersNum = 1;
- hfsPB.ioParam.ioPermssn = fsRdPerm;
- hfsPB.ioParam.ioMisc = 0L;
-
- fserr = PBOpen(&hfsPB, FALSE);
- if (fserr) {
- AlertUser(eDocOpenFail,fserr);
- CloseResFile(resfnum);
- (void)XTNDReleaseTranslator(pChosenOne);
- return;
- }
-
- importPB.refNum = fnum = hfsPB.ioParam.ioRefNum;
- importPB.directive = importInitAll;
- (*gImportTranslator)(&importPB);
-
- /* After completing the initialization, check for an error. If none, proceed. */
-
- if (importPB.result) {
- AlertUser(eDocReadFail,importPB.result);
- CloseResFile(resfnum);
- (void)XTNDReleaseTranslator(pChosenOne);
- return;
- }
-
- /* STAGE ONE - just read in the TEXT of the file. Ignore pictures */
-
- /* Set starting place to be the MAIN body of text. */
- importPB.directive = importInitMain;
- importPB.currentStory = mainStory;
- (*gImportTranslator) (&importPB);
- if (!importPB.result) {
-
- SetRect(&tempRect, 0, 0, 0, 0);
- ClipRect(&tempRect); /* close clip rect so text will not be drawn */
- GetDateTime(&now);
- while (textrun < 30000)
- {
-
- importPB.directive = importGetText;
- (*gImportTranslator) (&importPB);
-
- fserr = importPB.result;
- count = importPB.textLength;
-
- if (fserr || ((importPB.directive == importAcknowledge) && (count <= 0)))
- break;
-
- if (count == 1) /* Is it a special character ? */
- {
- if (Buffer[0] < 32)
- switch (Buffer[0])
- {
- case 2: /* Page Number */
- case 3: /* Footnote reference */
- case 5: /* Footnote reference */
- case 6: /* Merge Break Char */
- case 9: /* Tab */
- case 11: /* Column Break */
- case 12: /* Page Break */
- case 31: /* Discretionary Hyphen */
- count = 0;
- break;
-
- case 4: /* Picture */
- /* We have to dispose of the picture, even if we don't use it. */
- pm = (PictMisc **) importPB.miscData;
- DisposHandle( (Handle) (**pm).thePicture);
- DisposHandle( (Handle) pm);
- count = 0;
- break;
-
- case 21: /* Short Date */
- case 22: /* Abbrev Date */
- case 23: /* Long date */
- case 24: /* Abbrev + day Date */
- case 25: /* Long + day Date */
- if (importPB.miscData)
- IUDateString(importPB.miscData, shortDate, theNumber);
- else
- IUDateString(now, shortDate, theNumber);
- count = theNumber[0];
- BlockMove(&(theNumber[1]), Buffer, count);
- break;
-
- case 26: /* Time */
- if (importPB.miscData)
- IUTimeString(importPB.miscData, FALSE, theNumber);
- else
- IUTimeString(now, FALSE, theNumber);
- count = theNumber[0];
- BlockMove(&(theNumber[1]), Buffer, count);
- break;
-
- case 7: /* Hard Return */
- Buffer[0] = 13;
- break;
- }
- }
-
- if (count)
- {
- /* Boy, is TextEdit buggy ! We need to see if there is enough memory to add the textrun */
- dummyptr = NewPtr(count+TESlop);
- if (dummyptr == 0L)
- break;
- else
- DisposPtr(dummyptr);
-
- /* Translate the style to Styled TextEdit style */
- newStyle.tsFont = importPB.txtFont;
- newStyle.tsFace = (importPB.txtFace&QUICKDRAWSTYLES);
- if (newStyle.tsFace == 0) {
- aPtr = (short *)&newStyle.tsFace; /* Fix a bug in text edit */
- *aPtr = 0;
- }
- newStyle.tsSize = importPB.txtSize;
-
- RGBFromXTND(&newStyle.tsColor, importPB.txtColor);
-
- TESetStyle(doFont+doSize+doFace+doColor, &newStyle, true, te);
-
- /* Now add the number of characters to the text edit handle in this window */
-
- TEInsert(Buffer, count, te);
- if (fserr = MemError())
- break;
- textrun += count;
- /* NumToString(textrun, theNumber); */ /* Used for debugging. Shows count in window title */
- /* SetWTitle(window, theNumber); */
- }
- }
-
- importPB.directive = importCloseMain;
- (*gImportTranslator) (&importPB);
- }
- importPB.directive = importCloseAll;
- (*gImportTranslator) (&importPB);
-
- TECalText(te); /* calc line starts in TERecord*/
- TESetSelect(0, 0, te); /* Set insertion point*/
- AdjustScrollValues(window, true);
- SetRect(&tempRect, -8000, -8000, 8000, 8000);
- ClipRect(&tempRect); /* open clip rect so text will be drawn */
-
- if (resfnum)
- CloseResFile(resfnum);
-
- FSClose(fnum);
-
- (void)XTNDReleaseTranslator(pChosenOne);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* ReadPlainTextFile inserts the text from the TEXT document */
- /* specified by the Standard File reply record *pTheReply into the */
- /* TextEdit record specified by hTE. The file is assumed to be */
- /* initially closed. The file is opened, the text is inserted at the */
- /* current insertion point, the window’s scrollbars are adjusted, and */
- /* the file is closed. The user is alerted if an error occurred. */
- /* Note: This version of ReadPlainTextFile() is very simplistic. It */
- /* reads the text into a block in the heap in one shot, then inserts */
- /* it into the TE record. If the free memory isn’t at least twice the */
- /* size of the text file ReadPlainTextFile() will fail. It also does */
- /* not check the current size of the text of the TE record to guard */
- /* against overflow. And it assumes that the specified file actually */
- /* exists (which it may not if the Standard File reply record was not */
- /* actually filled in by a Standard File routine). */
- /*----------------------------------------------------------------------*/
- static OSErr ReadPlainTextFile(const SFReply *pTheReply, TEHandle hTE)
- {
- OSErr err;
- ParamBlockRec myPB;
- Handle hTx = NULL;
-
- /* open the text file… */
- myPB.ioParam.ioNamePtr = pTheReply->fName;
- myPB.ioParam.ioVRefNum = pTheReply->vRefNum;
- myPB.ioParam.ioVersNum = 0;
- myPB.ioParam.ioPermssn = fsRdPerm;
- myPB.ioParam.ioMisc = NULL;
- if ((err = PBOpen(&myPB, FALSE)) != noErr) {
- AlertUser(eDocOpenFail,err);
- return(err);
- }
- /* find out how much text in the file… */
- if ((err = PBGetEOF(&myPB, FALSE)) != noErr) {
- AlertUser(eDocOpenFail,err);
- } else {
- /* get a buffer for the text… */
- if (!(hTx = NewHandle((long)myPB.ioParam.ioMisc))) {
- AlertUser(eCreateFail,MemError());
- } else {
- MoveHHi(hTx);
- HLock(hTx);
- /* read the file into the buffer… */
- myPB.ioParam.ioBuffer = *hTx;
- myPB.ioParam.ioReqCount = (long)myPB.ioParam.ioMisc;
- myPB.ioParam.ioPosMode = fsFromStart;
- myPB.ioParam.ioPosOffset = 0L;
- if ((err = PBRead(&myPB, FALSE)) == noErr) {
- /* insert text from buffer into TE record… */
- TEInsert(*hTx, myPB.ioParam.ioActCount, hTE);
- /* adjust window’s scrollbars… */
- AdjustScrollValues((**hTE).inPort, true);
- }
- }
- }
- if (hTx)
- DisposHandle(hTx);
- PBClose(&myPB, FALSE);
- return(err);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* SaveFile saves the file using XTND. It loads the translator, */
- /* initializes the export parameter block, and sends commands to the */
- /* translator to write out the document. When it is finished, it */
- /* releases the translator. */
- /*----------------------------------------------------------------------*/
- static void SaveFile(pChosenOne, theReply)
- TransDescribe *pChosenOne;
- SFReply theReply;
- {
- register long loop;
- short fserr = 0, fnum;
- MatchInfo Match;
- ExportParmBlock exportPB;
- long runlength, bufferSize;
- Handle textbuffer;
- short textface, textsize, textfont, textjust, selStart, selEnd;
- char textcolor;
- Fixed Paragraph[9];
- TabSpec tabs[20];
- Point MinusOne;
- Rect tempRect;
- TEHandle te;
- WindowPtr window = FrontWindow();
- long start, end, stylerun;
- TEStyleHandle shndl;
-
- te = ((DocumentPeek) window)->docTE;
-
- /* In order to save the document, we have to parse our own document, and determine */
- /* where the paragraph and style runs start and end. This is not a simple project in */
- /* text edit! */
-
- /* First, let's load the Translator, just so we know we can ! */
- if (fserr = XTNDLoadTranslator(pChosenOne, &gExportTranslator)) {
- AlertUser(eTranslatorLoad,fserr);
- return;
- }
-
- /* Now, create the file so we can delete it. (Takes care of PMSP problem) */
- Create(theReply.fName, theReply.vRefNum, '????', '????');
- if (fserr = FSDelete(theReply.fName, theReply.vRefNum)) {
- /* Explain we couldn't delete the file - probably a write protect error */
- AlertUser(eDeleteFailed,fserr);
- } else {
- Match = pChosenOne->matches[0];
- if (fserr = Create(theReply.fName, theReply.vRefNum, Match.docCreator, Match.docType)) {
- AlertUser(eCreateFail,fserr);
- } else {
- if (fserr = FSOpen(theReply.fName, theReply.vRefNum, &fnum))
- AlertUser(eOpenFail,fserr);
- }
- }
-
- if (fserr) {
- (void)XTNDReleaseTranslator(pChosenOne);
- return;
- }
-
- Paragraph[0] = Paragraph[1] = Paragraph[2] = 0; /* indent offsets */
- Paragraph[3] = Paragraph[4] = Paragraph[5] = 0; /* leading/space before/after paragraph */
- Paragraph[6] = -1; /* leading units (lines) */
- Paragraph[7] = Paragraph[8] = 0; /* space before/after paragraph units (points) */
- for (loop = 0; loop < 20; tabs[loop++].tabIndent = -1L);
-
- /* Initialize the export Translator */
- SetRect(&tempRect, 0, 0, 0, 0);
- MinusOne.h = MinusOne.v = -1;
- textbuffer = NewHandle(256);
- bufferSize = 256;
- /* Check to see if this worked */
-
- exportPB.thePicture = nil;
- exportPB.pictRect = tempRect;
- exportPB.footnoteOffset = 0;
- exportPB.pagePoint = MinusOne;
- exportPB.datePoint = MinusOne;
- exportPB.timePoint = MinusOne;
-
- exportPB.textBuffer = textbuffer;
- exportPB.textLength = &runlength;
- exportPB.result = &fserr;
- exportPB.refNum = &fnum;
- exportPB.txtFace = &textface;
- exportPB.txtSize = &textsize;
- exportPB.txtFont = &textfont;
- exportPB.txtColor = &textcolor;
- exportPB.txtJust = &textjust;
- exportPB.paraFmts = Paragraph;
- exportPB.tabs = tabs;
- exportPB.footnoteText = nil;
-
- exportPB.topMargin = 0x00480000; /* 1 inch margin */
- exportPB.bottomMargin = 0x00480000; /* 1 inch margin */
- exportPB.leftMargin = 0x00480000; /* 1 inch margin */
- exportPB.rightMargin = 0x00480000; /* 1 inch margin */
- exportPB.gutter = 0x000C0000; /* 12 point column gap */
- exportPB.numCols = 1;
- exportPB.startPageNum = 1;
- exportPB.startFootnoteNum = 1;
- exportPB.currentStory = mainStory;
- exportPB.rulerShowing = TRUE;
- exportPB.doubleSided = FALSE;
- exportPB.titlePage = FALSE;
- exportPB.endnotes = FALSE;
- exportPB.showInvisibles = TRUE;
- exportPB.showPageGuides = TRUE;
- exportPB.showPictures = TRUE;
- exportPB.autoFootnotes = TRUE;
- exportPB.smartQuotes = TRUE;
- exportPB.fractCharWidths = TRUE;
- exportPB.hRes = 72;
- exportPB.vRes = 72;
- exportPB.windowRect = tempRect;
-
- exportPB.headerStatus = 0;
- exportPB.footerStatus = 0;
- exportPB.totalCharCount = end = (**te).teLength;
- exportPB.footnotesExist = FALSE;
-
- exportPB.theReply = theReply;
- exportPB.thisTranslator = *pChosenOne;
-
- selStart = (**te).selStart;
- selEnd = (**te).selEnd;
- SetRect(&tempRect, 0, 0, 0, 0);
- ClipRect(&tempRect); /* close clip rect so text will not be drawn */
-
- PrOpen();
- if (!PrError()) {
- exportPB.printRecord = (THPrint)NewHandle(sizeof(TPrint));
- if (exportPB.printRecord) {
- PrintDefault(exportPB.printRecord);
- PrValidate(exportPB.printRecord);
- }
- PrClose();
- } else
- exportPB.printRecord = 0L;
-
-
- exportPB.directive = exportInitAll;
- (*gExportTranslator) (&exportPB);
-
- /* OK - let's open the main story */
-
- exportPB.directive = exportOpenMain;
- exportPB.currentStory = mainStory;
- (*gExportTranslator) (&exportPB);
- if (!(*exportPB.result)) {
-
- shndl = GetStylHandle(te); /* There may not be _any_ style runs. */
- if (shndl) {
- StyleRun *sruns;
- Handle theText;
- long length, offset, textLength;
- STElement *styleruns, Anentry;
- char *TextPtr;
- STHandle thestyles;
-
- theText = (Handle) TEGetText(te);
- textLength = (**te).teLength;
- HLock(theText);
- TextPtr = *theText;
- HLock((Handle)shndl);
- sruns = (**shndl).runs;
- thestyles = (**shndl).styleTab;
- HLock((Handle)thestyles);
- styleruns = *thestyles;
- for (stylerun = 0; stylerun < (**shndl).nRuns; stylerun++, sruns++) {
- start = sruns->startChar;
- length = (sruns + 1)->startChar - start;
- if (length + start > textLength)
- length = textLength - start;
- runlength = offset = 0;
- /* Find the associated style entry */
- Anentry = (styleruns)[sruns->styleIndex];
- textface = Anentry.stFace;
- textsize = Anentry.stSize << 2; /* multiply by four to simulate MacWrite II font size */
- textcolor = RGBToXTND(Anentry.stColor);
- textfont = Anentry.stFont;
- textjust = 0; /* left; */
- while (offset + runlength < length) {
- while (offset + runlength < length)
- if (TextPtr[runlength++] == 13)
- break;
- /* Send runlength characters, starting at start + offset */
- SetHandleSize(textbuffer, runlength);
- /* check to see if this fails */
- if (runlength > bufferSize)
- SetHandleSize(textbuffer, bufferSize = runlength);
- BlockMove(TextPtr, *textbuffer, runlength);
- exportPB.directive = exportWriteText;
- (*gExportTranslator) (&exportPB);
- TextPtr += runlength;
- TESetSelect(start + offset, start + offset + runlength, te);
- offset += runlength;
- runlength = 0;
- }
- }
- }
- exportPB.directive = exportCloseMain;
- (*gExportTranslator) (&exportPB);
- }
- exportPB.directive = exportCloseAll;
- (*gExportTranslator) (&exportPB);
-
- if (exportPB.printRecord)
- DisposHandle( (Handle) exportPB.printRecord);
- FSClose(fnum);
-
- /* Write resource fork now. */
- {
- Str255 vName;
- short vRefNum;
-
- GetVol(vName, &vRefNum);
- SetVol(0L, theReply.vRefNum);
- CreateResFile(theReply.fName);
- fnum = OpenResFile(theReply.fName);
- exportPB.directive = exportWriteResources;
- (*gExportTranslator) (&exportPB);
- CloseResFile(fnum);
- SetVol(0L, vRefNum);
- }
-
- (void)XTNDReleaseTranslator(pChosenOne);
-
- TESetSelect(selStart, selEnd, te); /*Set insertion point*/
- SetRect(&tempRect, -8000, -8000, 8000, 8000);
- ClipRect(&tempRect); /* open clip rect so text will be drawn */
- }
-
-
- /*----------------------------------------------------------------------*/
- /* SavePlainTextFile saves the text from the TextEdit record specified */
- /* by hTE to the file having the name fileName on the volume specified */
- /* by vRefNum and in the directory specified by dirID. The file is */
- /* assumed to be initially closed. It is opened, the text written out */
- /* (replacing any previous contents of the file), and the file is */
- /* closed. If saveAll is TRUE the entire text of the edit record is */
- /* written out, otherwise only the text within the current selection */
- /* is saved. The user is alerted if an error occured. */
- /*----------------------------------------------------------------------*/
- static OSErr SavePlainTextFile(Str255 fileName, short vRefNum, long dirID,
- TEHandle hTE, Boolean saveAll)
- {
- OSErr err;
- SignedByte mfb;
- HParamBlockRec myHPB;
-
- /* open the file… */
- myHPB.ioParam.ioNamePtr = fileName;
- myHPB.ioParam.ioVRefNum = vRefNum;
- myHPB.ioParam.ioVersNum = 0;
- myHPB.ioParam.ioPermssn = fsRdWrPerm;
- myHPB.ioParam.ioMisc = NULL;
- myHPB.fileParam.ioDirID = dirID;
- if ((err = PBHOpen(&myHPB, FALSE)) != noErr) {
- AlertUser(eOpenFail,err);
- return(err);
- }
- /* reset eof of file to zero… */
- myHPB.ioParam.ioMisc = 0L;
- if ((err = PBSetEOF((ParmBlkPtr)&myHPB, FALSE)) != noErr) {
- AlertUser(eOpenFail,err);
- } else {
- /* temporarily lock down text block of TE record;
- this is paranoia since PBWrite() is not supposed to move/purge memory… */
- MoveHHi((**hTE).hText);
- mfb = HGetState((**hTE).hText);
- HLock((**hTE).hText);
- /* write out TE text to file & reset lock-state of text block… */
- myHPB.ioParam.ioBuffer = *(**hTE).hText + ((saveAll) ? 0 : (**hTE).selStart);
- myHPB.ioParam.ioReqCount = (saveAll) ? (**hTE).teLength : (**hTE).selEnd - (**hTE).selStart;
- myHPB.ioParam.ioPosMode = fsFromStart;
- myHPB.ioParam.ioPosOffset = 0L;
- err = PBWrite((ParmBlkPtr)&myHPB, FALSE);
- HSetState((**hTE).hText, mfb);
- }
- (void)PBClose((ParmBlkPtr)&myHPB, FALSE);
- return(err);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* SaveNewPlainTextFile creates a new file and saves the text from the */
- /* TextEdit record specified by hTE. The file is created with a */
- /* creator of 'XTND' and filetype fileType. The name and location of */
- /* the file is specified by the Standard File reply record *pTheReply. */
- /* The directory ID and real volume reference number of the specified */
- /* location are returned through the VAR parameters *pVRefNum and */
- /* *pDirID. Any existing file is first deleted. The file is closed */
- /* after saving its contents. If saveAll is TRUE the entire text of */
- /* the edit record is written out, otherwise only the text within the */
- /* current selection is saved. If an error occured the user is alerted */
- /* and the file is deleted. */
- /*----------------------------------------------------------------------*/
- static OSErr SaveNewPlainTextFile(const SFReply *pTheReply, OSType fileType,
- TEHandle hTE, Boolean saveAll, short *pVRefNum, long *pDirID)
- {
- OSErr err;
- WDPBRec myWDPB;
- HParamBlockRec myHPB;
-
- /* get the dirID and real vRefNum… */
- myWDPB.ioNamePtr = NULL;
- myWDPB.ioVRefNum = pTheReply->vRefNum;
- myWDPB.ioWDIndex = 0;
- myWDPB.ioWDProcID = 0L;
- if ((err = PBGetWDInfo(&myWDPB, FALSE)) != noErr) {
- AlertUser(eCreateFail,err);
- return(err);
- }
- /* delete file (if it already exists)… */
- myHPB.ioParam.ioNamePtr = pTheReply->fName;
- myHPB.ioParam.ioVRefNum = *pVRefNum = myWDPB.ioWDVRefNum;
- myHPB.ioParam.ioVersNum = 0;
- myHPB.fileParam.ioDirID = *pDirID = myWDPB.ioWDDirID;
- if ((err = PBHDelete(&myHPB, FALSE)) != noErr && err != fnfErr) {
- /* …possibly locked or busy, or who knows what */
- AlertUser(eDeleteFailed,err);
- return(err);
- }
- /* create the file… */
- if ((err = PBHCreate(&myHPB, FALSE)) != noErr) {
- AlertUser(eCreateFail,err);
- return(err);
- }
- /* write text to file… */
- if (!(err = SavePlainTextFile(pTheReply->fName, myWDPB.ioWDVRefNum, myWDPB.ioWDDirID, hTE, saveAll)))
- {
- /* set filetype & creator information… */
- myHPB.fileParam.ioFDirIndex = 0;
- if ((err = PBHGetFInfo(&myHPB, FALSE)) == noErr) {
- myHPB.fileParam.ioDirID = myWDPB.ioWDDirID;
- myHPB.fileParam.ioFlFndrInfo.fdType = fileType;
- myHPB.fileParam.ioFlFndrInfo.fdCreator = 'XTND';
- err = PBHSetFInfo(&myHPB, FALSE);
- }
- }
- if (err != noErr) {
- AlertUser(eCreateFail,err);
- (void)PBHDelete(&myHPB, FALSE);
- }
- return(err);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* GetNextStory will send the appropriate directive to the translator */
- /* to request the next story depending on the current story. */
- /*----------------------------------------------------------------------*/
- static void Getnextstory(thePtr)
- register ImportParmBlkPtr thePtr;
-
- {
- while (thePtr->directive != importAcknowledge)
- {
-
- (*gImportTranslator)(thePtr);
-
- switch(thePtr->directive)
- {
- default:
- thePtr->directive = importAcknowledge;
- break;
-
- case importInitRightHeader:
- thePtr->currentStory = leftHeaderStory;
- thePtr->directive = importInitLeftHeader;
- break;
-
- case importInitLeftHeader:
- thePtr->currentStory = headerStory;
- thePtr->directive = importInitHeader;
- break;
-
- case importInitHeader:
- thePtr->currentStory = rightFooterStory;
- thePtr->directive = importInitRightFooter;
- break;
-
- case importInitRightFooter:
- thePtr->currentStory = leftFooterStory;
- thePtr->directive = importInitLeftFooter;
- break;
-
- case importInitLeftFooter:
- thePtr->currentStory = footerStory;
- thePtr->directive = importInitFooter;
- break;
-
- case importInitFooter:
- thePtr->currentStory = mainStory;
- thePtr->directive = importInitMain;
- break;
- }
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- /* RGBToXTND converts a RGB color to the corresponding XTND color */
- /* value, which, although it is in the range from 0 to 7, is NOT the */
- /* same as the QuickDraw color values. */
- /*----------------------------------------------------------------------*/
- short RGBToXTND(theColor)
- RGBColor theColor;
- {
- register short r,g,b;
- /* ColorMap contains the conversion from QuickDraw color to our color id */
- static short colormap[8] = {1,4,3,5,2,6,7,0};
-
- r = theColor.red & 0x8000 ? 4:0;
- g = theColor.green & 0x8000 ? 2:0;
- b = theColor.blue & 0x8000 ? 1:0;
- return (colormap[r+g+b]);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* RGBFromXTND an XTND color value to the corresponding RGB color */
- /* value. XTND color values are NOT the same as QuickDraw colors. */
- /*----------------------------------------------------------------------*/
- void RGBFromXTND(rgb, colorcode)
- RGBColor *rgb;
- short colorcode;
- {
- switch(colorcode)
- {
- case 0: /* WHITE */
- rgb->red = rgb->green = rgb->blue = 65535; break;
- case 1: /* BLACK */
- rgb->red = rgb->green = rgb->blue = 0; break;
- case 2: /* RED */
- rgb->red = 65535; rgb->green = rgb->blue = 0; break;
- case 3: /* GREEN */
- rgb->red = rgb->blue = 0; rgb->green = 65535; break;
- case 4: /* BLUE */
- rgb->red = rgb->green = 0; rgb->blue = 65535; break;
- case 5: /* CYAN */
- rgb->red = 0; rgb->green = rgb->blue = 65535; break;
- case 6: /* MAGENTA */
- rgb->red = rgb->blue = 65535; rgb->green = 0; break;
- case 7: /* YELLOW */
- rgb->red = rgb->green = 65535; rgb->blue = 0; break;
- }
- }
-
- /*------------------------------------------------------------------------------*/
- void ZeroBlock(block, size)
- register void *block;
- register long size;
- {
- register Ptr blockPtr;
- register long *longPtr;
-
- blockPtr = block;
-
- while (size & 3) /* while (size % sizeof(long)) */
- blockPtr[--size] = 0;
-
- if (!size) return;
-
- longPtr = (long *) block;
- size >>= 2; /* size /= sizeof(long) */
-
- while (size--)
- *longPtr++ = 0L;
- } /* ZeroBlock */
-
-